#region File Description
//-----------------------------------------------------------------------------
// File:      DisplaySettingsDialog.cs
// Namespace: WindowSystem
// Author:    Aaron MacDougall
//-----------------------------------------------------------------------------
#endregion

#region License
//-----------------------------------------------------------------------------
// Copyright (c) 2007, Aaron MacDougall
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of Aaron MacDougall nor the names of its contributors may
//   be used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using InputEventSystem;
#endregion

namespace WindowSystem
{
    /// <summary>
    /// A dialog box that allows the user to set the display resolution, and
    /// choose between fullscreen and windowed modes.
    /// </summary>
    public class DisplaySettingsDialog : Dialog
    {
        private const int LargeSeperation = 10;
        private const int SmallSeperation = 5;
        private CheckBox fullscreenCheckBox;
        private Label resolutionLabel;
        private ComboBox resolutionCombo;
        
        private TextButton OKButton;
        private TextButton cancelButton;
        private TextButton applyButton;
        private GraphicsDeviceManager graphics;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="game">The currently running Game object.</param>
        /// <param name="guiManager">GUIManager that this control is part of.</param>
        /// <param name="graphics">Graphics device manager to change settings.</param>
        public DisplaySettingsDialog(Game game, GUIManager guiManager, GraphicsDeviceManager graphics) : base(game, guiManager)
        {
            

            this.fullscreenCheckBox = new CheckBox(game, guiManager);
            this.resolutionLabel = new Label(game, guiManager);
            this.resolutionCombo = new ComboBox(game, guiManager);
            this.OKButton = new TextButton(game, guiManager);
            this.cancelButton = new TextButton(game, guiManager);
            this.applyButton = new TextButton(game, guiManager);
            

            
            Add(this.fullscreenCheckBox);
            Add(this.resolutionLabel);
            Add(this.resolutionCombo);
            Add(this.OKButton);
            Add(this.cancelButton);
            Add(this.applyButton);
            

            this.graphics = graphics;

            // Set checkbox to current value
            fullscreenCheckBox.Checked = graphics.IsFullScreen;

            // Populate combobox
            //resolutionCombo.AddEntry("3280x2048");
            resolutionCombo.AddEntry("2560x1600");
            resolutionCombo.AddEntry("2048x1536");

            resolutionCombo.AddEntry("1920x1200");
            resolutionCombo.AddEntry("1920x1080");

            //resolutionCombo.AddEntry("1792x1344");
            resolutionCombo.AddEntry("1680x1050");
            resolutionCombo.AddEntry("1600x1200");
            resolutionCombo.AddEntry("1440x900");
            resolutionCombo.AddEntry("1366x768");
            //resolutionCombo.AddEntry("1360x768");

            resolutionCombo.AddEntry("1280x1024");
            resolutionCombo.AddEntry("1280x960");
            resolutionCombo.AddEntry("1280x800");
            resolutionCombo.AddEntry("1280x768");
            resolutionCombo.AddEntry("1280x720");

            resolutionCombo.AddEntry("1152x864");
            resolutionCombo.AddEntry("1024x768");
            resolutionCombo.AddEntry("800x600");
            //resolutionCombo.AddEntry("640x480");
            //resolutionCombo.AddEntry("320x200");

            // Set combobox to current value
            var currentRes = resolutionCombo.Items.SingleOrDefault(o => o.Text == graphics.PreferredBackBufferWidth + "x" + graphics.PreferredBackBufferHeight);
            resolutionCombo.SelectedIndex = currentRes == null ? 0 : currentRes.Key;

            // Child settings
            TitleText = "Display Settings";
            fullscreenCheckBox.Text = "Fullscreen";
            resolutionLabel.Text = "Select desired display resolution";
            resolutionLabel.Width = resolutionLabel.TextWidth;
            resolutionCombo.IsEditable = false;
            OKButton.Text = "OK";
            cancelButton.Text = "Cancel";
            applyButton.Text = "Apply";
            Resizable = false;

            // Layout
            this.fullscreenCheckBox.X = LargeSeperation;
            this.fullscreenCheckBox.Y = LargeSeperation;
            this.resolutionLabel.X = LargeSeperation;
            this.resolutionLabel.Y = this.fullscreenCheckBox.Y + this.fullscreenCheckBox.Height + LargeSeperation;
            this.resolutionCombo.X = LargeSeperation;
            this.resolutionCombo.Y = this.resolutionLabel.Y + this.resolutionLabel.Height + SmallSeperation;
            this.OKButton.Y = this.resolutionCombo.Y + this.resolutionCombo.Height + (LargeSeperation * 2);
            this.cancelButton.Y = this.OKButton.Y;
            this.applyButton.Y = this.OKButton.Y;

            // Check if buttons require more space
            var buttonsWidth = this.OKButton.Width + this.cancelButton.Width + this.applyButton.Width + (2 * SmallSeperation);

            if (buttonsWidth > this.resolutionCombo.Width)
            {
                this.resolutionCombo.Width = buttonsWidth;
                ClientWidth = buttonsWidth + (2 * LargeSeperation);
            }
            else
                ClientWidth = this.resolutionCombo.Width + (2 * LargeSeperation);

            ClientHeight = applyButton.Y + applyButton.Height + LargeSeperation;

            PositionWindow();

            // Align buttons to the right of the window
            cancelButton.X = ClientWidth - cancelButton.Width - LargeSeperation;
            applyButton.X = cancelButton.X - applyButton.Width - SmallSeperation;
            OKButton.X = applyButton.X - applyButton.Width - SmallSeperation;

            OKButton.Click += OnOK;
            cancelButton.Click += OnCancel;
            applyButton.Click += OnApply;

        }

        private void PositionWindow()
        {
            X = (graphics.PreferredBackBufferWidth / 2) - (Width / 2);
            Y = (graphics.PreferredBackBufferHeight / 2) - (Height / 2);
        }

        /// <summary>
        /// Applies settings.
        /// </summary>
        protected void Apply()
        {
            if (!string.IsNullOrEmpty(resolutionCombo.SelectedText))
            {
                var res = resolutionCombo.SelectedText.Split('x');

                var newWidth = Convert.ToInt32(res[0]);
                var newHeight = Convert.ToInt32(res[1]);

                if (this.graphics.PreferredBackBufferWidth != newWidth || this.graphics.PreferredBackBufferHeight != newHeight)
                {
                    this.graphics.PreferredBackBufferWidth = newWidth;
                    this.graphics.PreferredBackBufferHeight = newHeight;
                    this.graphics.ApplyChanges();
                }                
            }

            //graphics.IsFullScreen = fullscreenCheckBox.Checked;

            if (this.fullscreenCheckBox.Checked && !this.graphics.IsFullScreen)
                this.graphics.ToggleFullScreen();
            else if (!this.fullscreenCheckBox.Checked && this.graphics.IsFullScreen)
                this.graphics.ToggleFullScreen();

            PositionWindow();
        }

       
        /// <summary>
        /// When the user clicks on the OK button, settings are applied, and
        /// dialog is closed.
        /// </summary>
        /// <param name="sender"></param>
        protected void OnOK(UIComponent sender)
        {
            Apply();
            SetDialogResult(DialogResult.OK);
            CloseWindow();
        }

        /// <summary>
        /// When the user clicks on the Cancel button, dialog is closed without
        /// applying changes.
        /// </summary>
        /// <param name="sender"></param>
        protected void OnCancel(UIComponent sender)
        {
            CloseWindow();
        }

        /// <summary>
        /// Apply changes without closing the dialog.
        /// </summary>
        /// <param name="sender"></param>
        protected void OnApply(UIComponent sender)
        {
            Apply();
        }
    }
}